#include <Riostream.h>
#include <TString.h>

#include <CpLog.h>

#include "CpMagneticField.h"

ClassImp(CpMagneticField);

//_________________________________________________________________
CpMagneticField::CpMagneticField(): TObject(),
   fMagneticParticle(),
   fMapType(kMapOneType),
   fAnalyticFunction(0)
{
//=====================
// Constructor
//=====================
}

//_________________________________________________________________
CpMagneticField::~CpMagneticField()
{
//=====================
// Destructor
//=====================
}

//_________________________________________________________________
void CpMagneticField::Print()
{
//=====================
// Prints info
//=====================

   CpInfo(Form("Mi_0\t= %e ", Mi_0()));
   CpInfo(Form("V_p\t= %e ", fMagneticParticle.Volume()));
   CpInfo(Form("M_p\t= %e ", M_p()));
   CpInfo(Form("dH\t= %e ", GradientOfMagneticField(fMagneticFieldType, 1.0)));

   CpInfo(Form("F_m\t= %e ", Force()));
}
Double_t Force();
//_________________________________________________________________
Double_t CpMagneticField::Force(Double_t value)
{
//=====================
// Calculate Force of the magnetic field
//=====================

   return Mi_0() * fMagneticParticle.Volume() * M_p() * GradientOfMagneticField(fMagneticFieldType, value);
}


//_________________________________________________________________
Double_t CpMagneticField::GradientOfMagneticField(EMagneticField type, Double_t value)
{
//=====================
// Calculate Gradient of the magnetic field
//=====================
   switch (type) {
      case kAnalytic:
         return GradientOfMagneticFieldAnalytic(value);
      case kMap:
         return 2.0;
      default:
         CpError("Wrong parameter of the field. Returning 0.0 ...");
   }

   return 0.0;
}

//_________________________________________________________________
Double_t CpMagneticField::GradientOfMagneticFieldAnalytic(Double_t value)
{
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

   if (!fAnalyticFunction) {
      CpError("Analytic function is not defined !!! Returning 0.0");
      return 0.0;
   }

   return fAnalyticFunction->Derivative(value);
}

//_________________________________________________________________
void CpMagneticField::SetAnalyticFunction(TString functionString, Double_t min, Double_t max)
{
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

   if (fAnalyticFunction) {
      delete fAnalyticFunction;
      fAnalyticFunction = 0;
   }

   fAnalyticFunction = new TF1("func", functionString.Data(), min, max);

}

//_________________________________________________________________
Double_t CpMagneticField::ValueAtAnalyticFunction(Double_t value)
{
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

   if (fAnalyticFunction) {
      CpError("Analytic function is not defined !!! Returning 0.0");
      return 0.0;
   }

   return fAnalyticFunction->Eval(value);

}
